package view.trajectory;

import java.util.Iterator;

import javax.media.opengl.GL;

import mathematics.geometry.PolylineGeometry;
import model.BaseModel;
import model.RoomModel;
import model.path.Point4D;
import model.trajectory.RoomTrajectoryModel;

import settings.Settings;
import utils.Point3D;
import utils.TimeIntervalle;
import utils.Vector3D;
import view.RoomView;

public class RoomTrajectoryView extends BaseTrajectoryView
{
	public RoomView room;
	
	public RoomTrajectoryView(GL gl, BaseModel model, RoomView room)
	{
		super(model);
		this.setGeometry(new PolylineGeometry());
		this.room = room;
	}

	public boolean mustDraw()
	{
		return !this.getGeometry().isEmpty();
	}
	
	@Override
	public void update(long time, long beginTime, long endTime)
	{
		this.getGeometry().clear();
		TimeIntervalle timeSpan = new TimeIntervalle(beginTime, endTime);
		RoomTrajectoryModel model = (RoomTrajectoryModel)this.getModel();
		if( !timeSpan.include(model.intervalle.beginTime) && !timeSpan.include(model.intervalle.endTime))
		{
			return;
		}
		else if(!this.room.isNodeShape())
		{
			if(this.getLastSubtrajectory() != null && !this.getLastSubtrajectory().getGeometry().isEmpty())
			{
				this.getGeometry().add(this.getLastSubtrajectory().getGeometry().get(this.getLastSubtrajectory().getGeometry().size()-1));
			}
			for(Iterator<Point4D> it = model.positions.iterator(); it.hasNext();)
			{
				Point3D point = it.next();
				this.getGeometry().add(new Point3D(point.x() + model.room.getPosition().x(), point.y() + model.room.getPosition().y()));
			}
		}
		else
		{	
			float startAngle;
			if(this.getLastSubtrajectory() != null && !this.getLastSubtrajectory().getGeometry().isEmpty() )
			{
				Vector3D lastSegmentVector = new Vector3D(Point3D.sum(this.room.getModel().getPosition(), ((RoomModel)this.room.getModel()).getCenter()), this.getLastSubtrajectory().getGeometry().get(this.getLastSubtrajectory().getGeometry().size()-1));
				startAngle = (float) lastSegmentVector.angle();
			}
			else if(this.getNextSubtrajectory() != null && !this.getNextSubtrajectory().getGeometry().isEmpty())
			{
				Vector3D nextSegmentVector = new Vector3D(Point3D.sum(this.room.getModel().getPosition(), ((RoomModel)this.room.getModel()).getCenter()), this.getNextSubtrajectory().getGeometry().get(0));
				startAngle = (float) nextSegmentVector.angle();

			}
			else
			{
				startAngle = 0;
			}
			
			float endAngle;
			if(this.getNextSubtrajectory() != null && !this.getNextSubtrajectory().getGeometry().isEmpty() )
			{
				Vector3D nextSegmentVector = new Vector3D(Point3D.sum(this.room.getModel().getPosition(), ((RoomModel)this.room.getModel()).getCenter()), this.getNextSubtrajectory().getGeometry().get(0));
				endAngle = (float) nextSegmentVector.angle();
			}
			else
			{
				endAngle = -0.00001f;
			}
			
			
			float angleExtent = endAngle - startAngle;
			if(angleExtent < 0)
			{
				angleExtent = (float) (2 * Math.PI + angleExtent);
			}
			if(this.getNextSubtrajectory() == null || this.getLastSubtrajectory() == null)
			{
				angleExtent = (float) (2 * Math.PI);
			}
			
			
			double radius;
	
			
			double offset = room.getTotalMaxOffset() / 2.0f;
			if(offset < Settings.NodeTrajectoryOffset)
			{
				radius = (long) (this.room.nodeSize / 2.0f); 
				radius += (Settings.NodeTrajectoryOffset )* (this.room.getIndexOfSubtrajectory(this, time, beginTime, endTime) + 1);	
			}
			else
			{
				radius = (long) (this.room.nodeSize / 2.0f);
				radius += (offset)* (this.room.getIndexOfSubtrajectory(this, time, beginTime, endTime) + 1);	
			}
			int numSides = (int) ((int)( Math.abs(angleExtent) * radius + 1 )  / 10.0f);
	        float deltaAngle = angleExtent / numSides;
			
	        for ( int j = 0; j <= numSides; ++j ) 
	        {	
        		float angle = ( startAngle + j * deltaAngle );
        		double x = ((RoomModel)this.room.getModel()).getCenter().x() + this.room.getModel().getPosition().x() + radius * Math.cos(angle);
        		double y = ((RoomModel)this.room.getModel()).getCenter().y() + this.room.getModel().getPosition().y() + radius * Math.sin(angle);
        		getGeometry().add(new Point3D( x, y));
	        }
		}
	}

	@Override
	public void update() {
		// TODO Auto-generated method stub
		
	}
}
